import { useState, useEffect, useRef } from 'react'
import { useNavigate } from 'react-router-dom'
import { NavBar, Toast } from 'antd-mobile'
import { getCityListAPI, getHotCityListAPI } from '../../api'
import './index.scss'
import getCurrentCityName from '../../utils/getCurrentCityName' // 获取当前城市的方法,Pormise
import { List, AutoSizer } from 'react-virtualized' // 引入List组件
import NavHeader from '../../components/NavHeader'

function CityList() {
  // 给List组件，创建ref对象
  const listRef = useRef(null)
  // console.log(listRef)
  const navigate = useNavigate()
  // 城市列表数据
  const [cityList, setCityList] = useState({})
  // 右侧索引数据
  const [cityIndex, setCityIndex] = useState([])
  // 添加状态，指定当前右侧高亮的索引
  const [activeIndex, setActiveIndex] = useState(0)

  // 数据格式化的方法，处理数据
  const formatCityData = (list) => {
    // 接口返回的数据格式：[{“label”：“北京”，“value”：“”，“pinyin”：“beijing”，“short”：“bj”}]
    // 渲染城市列表的数据格式：{a:[{},{}] , b:[{},{}]}
    // 渲染右侧索引的数据格式：['a','b']
    // 定义城市列表数据
    const cityListFormat = {}
    // 1.遍历list
    list.forEach((item) => {
      // 2.获取每一个城市的首字母
      const firstIndex = item.short.substring(0, 1)
      // 3.判断cityListFormat中是否有该分类
      if (cityListFormat[firstIndex]) {
        // 4.如果有，直接往该分类中push数据
        cityListFormat[firstIndex].push(item)
      } else {
        // 5.如果没有，就先创建一个数组，然后把当前城市信息添加到数组
        cityListFormat[firstIndex] = [item]
      }
    })
    // 获取右侧索引数据
    const indexListFormat = Object.keys(cityListFormat).sort()

    // 将数据返回出去
    return {
      cityListFormat,
      indexListFormat,
    }
  }

  useEffect(() => {
    // 获取城市列表数据的方法
    const loadCityList = async () => {
      const { data: res } = await getCityListAPI(1) // 调接口获取城市列表
      // 调用数据格式化的方法 formatCityData
      const { cityListFormat, indexListFormat } = formatCityData(res.body)
      // 获取热门城市数据
      const { data: hotRes } = await getHotCityListAPI()
      cityListFormat['hot'] = hotRes.body // 热门城市数据添加到 cityListFormat
      indexListFormat.unshift('hot') // 热门城市索引添加到 indexListFormat
      // 获取当前定位城市
      const curCity = await getCurrentCityName()
      // console.log(JSON.parse(curCity), 'curCity')
      cityListFormat['#'] = [JSON.parse(curCity)] // 将当前定位城市数据添加到 cityListFormat
      indexListFormat.unshift('#') // 索引添加到 indexListFormat

      // console.log(cityListFormat, indexListFormat)

      setCityList(cityListFormat) // 更新城市列表数据
      setCityIndex(indexListFormat) // 更新右侧索引数据
    }
    loadCityList() // 调用城市列表数据的方法

    // 点击索引无法正确定位的问题。调用List组件的 measureAllRows,提前计算 List中每一行的高度，实现 scrollToRow的精确跳转。
    // 注意：调用这个方法的时候，需要保证List组件已经有数据了，如果List组件中的数据为空，就会导致调用方法报错。
    // 解决：只要保证这个方法是在 获取到数据之后 调用即可。
    // listRef.current.measureAllRows()
  }, [])

  // 可视区域渲染模块
  // 处理索引号
  const formatCityIndex = (letter) => {
    switch (letter) {
      case '#':
        return '当前定位'
      case 'hot':
        return '热门城市'
      default:
        return letter.toUpperCase()
    }
  }
  // 创建动态计算每一行高度的方法
  const formatRowHeight = ({ index }) => {
    // 这里的index是 rowHeight 返回的的索引
    // 公式：索引标题高度(36) + 城市数量 * 城市名称高度(50)
    const num = cityList[cityIndex[index]].length
    return 36 + num * 50
  }
  // 列表数据的数据源
  // const list = Array(100).fill('react')
  // List组件数据渲染
  function rowRenderer({
    key, // 行数组中的唯一键
    index, // 索引号
    isScrolling, // 当前项是否正在滚动
    isVisible, // 当前项在List是可见的
    style, // 重点属性，一定要给每一行数据添加该样式！作用：指定每一行的位置
  }) {
    const letter = cityIndex[index] // 拿到城市索引

    return (
      <div key={key} style={style} className="city">
        {/* 展示索引，需要调用 formatCityIndex 函数处理一下 */}
        <div className="title">{formatCityIndex(letter)}</div>
        {/* 展示城市名称 */}
        {cityList[letter].map((item) => (
          <div
            className="name"
            key={item.value}
            // 切换城市
            onClick={() => changeCity(item)}
          >
            {item.label}
          </div>
        ))}
      </div>
    )
  }
  // 封装渲染城右侧市索引列表方法
  const renderCityIndex = () => {
    return cityIndex.map((item, index) => (
      <li
        className="city-index-item"
        key={item}
        onClick={() => {
          // 调用List组件中的scrollToRow方法，实现点击索引跳转到指定行
          listRef.current.scrollToRow(index)
        }}
      >
        {/* 动态显示索引的高亮效果 */}
        <span className={activeIndex === index ? 'index-active' : ''}>
          {item === 'hot' ? '热' : item.toUpperCase()}
        </span>
      </li>
    ))
  }
  // 获取当前列表渲染的行信息,实现滚动当前高亮
  const onRowsRendered = ({ startIndex }) => {
    // startIndex,就是起始索引，也就是可视区域最顶部一行的索引号。
    // 当 startIndex 和 activeIndex 不同的时候，更新 activeIndex 的值为 startIndex
    if (startIndex !== activeIndex) {
      setActiveIndex(startIndex)
    }
  }

  // 切换城市
  const changeCity = ({ label, value }) => {
    // 有房源的城市，只有北上广深
    const HOUSE_CITY = ['北京', '上海', '广州', '深圳']
    if (HOUSE_CITY.indexOf(label) > -1) {
      // 有房源数据，保存当前城市数据到本地缓存，并返回上一页。
      localStorage.setItem('hkzf_city', JSON.stringify({ label, value }))
      navigate(-1) // 返回上一页
    } else {
      // 无房源的城市，提示用户：该城市暂无房源数据，不执行任何操作。
      Toast.show({
        content: '该城市暂无房源数据',
        // afterClose: () => {
        //   console.log('after')
        // },
      })
    }
  }

  // 渲染UI
  return (
    <div className="cityList">
      {/* <NavBar back="返回" onBack={() => navigate(-1)}>
        城市选择
      </NavBar> */}
      {/* 导入顶部导航组件 */}
      <NavHeader title="城市选择"></NavHeader>
      {/* 城市列表组件 */}
      <AutoSizer>
        {({ width, height }) => (
          <List
            width={width}
            height={height}
            rowCount={cityIndex.length}
            // rowHeight 可以是number或者是function，声明一个函数，动态计算每一行高度的方法
            rowHeight={formatRowHeight}
            // 渲染UI
            rowRenderer={rowRenderer}
            // 获取当前列表渲染的行信息
            onRowsRendered={onRowsRendered}
            // 绑定ref
            ref={listRef}
            // scrollToAlignment配置项为 start，保证点击索引的时候，被点击行出现在页面顶部
            scrollToAlignment="start"
          />
        )}
      </AutoSizer>

      {/* 右侧城市列表索引 */}
      <ul className="city-index">{renderCityIndex()}</ul>
    </div>
  )
}

export default CityList
